<!--
 * @Author: wangshuixin 2412658453@qq.com
 * @Date: 2024-11-08 10:09:37
 * @LastEditors: wangshuixin 2412658453@qq.com
 * @LastEditTime: 2024-11-08 12:20:41
 * @FilePath: \web-components-box\components\ElementUI\TableForm\index.vue
 * @Description: 表格组件
-->

<script setup lang="ts">
import { ElMessage } from 'element-plus'
import type { TableColumnItem } from '@/types/component'
import ToolBar from "./ToolBar.vue";
import { ref, watch } from "vue";

const props = defineProps({
  data: { // 数据
    type: Array,
    required: true,
    default: () => [],
  },
  tableLoading: { // 加载loading
    type: Boolean,
    default: false,
  },
  columns: { // 表头设置
    type: Array as () => TableColumnItem[],
    default: []
  },
  showPagination: { // 显示分页选择器
    type: Boolean,
    default: true,
  },
  totalCount: { // 数据总条数
    type: Number,
    default: 0
  },
  /* 表格最大高度 */
  maxHeight: {
   type: String,
   default: '600px'
  },
  showRowSelection: { // 显示行选择器
    type: Boolean,
    default: false
  },
  paginationLayout: {
   type: String,
    default: 'total, sizes, prev, pager, next, jumper'
  },
  pageSize: {
    type: Number,
    default: 10
  },
  download: { // 下载回调函数
   type: Function,
  },
  pageSizes: { // 页码可选参数
    type: Array,
    default() {
      return [10, 20, 30, 50]
    }
  },
  /* 展示表格toolBar工具栏 */
  showToolBar: {
    type: Boolean,
    default: true,
  },
  btnTitle: {
    type: String,
    default: '按钮'
  },
  /* 隐藏toolBar左边菜单 */
  hideLeftMenu: {
    type: Boolean,
    default: true,
  },
  /* 是否显示检索条件 */
  showSearch: {
    type: Boolean,
    default: true,
  },
  /* 是否显示检索图标 */
  showSearchIcon: {
    type: Boolean,
    default: true,
  },
  /* 显隐列类型（transfer穿梭框、checkbox复选框） */
  showColumnsType: {
    type: String,
    default: "checkbox",
  },
})

const emits = defineEmits(['update:showSearch', 'refresh', 'selectRows', 'rowDblclick', 'btnClick'])

// 当前分页
const currentPage = ref(1)
// 分页尺寸
const currentPageSize = ref(props.pageSize)
// 选中的每行数据的id
const ids = ref([])
// 显隐列数据
const columnsList = ref<TableColumnItem[]>([])

// 行选择器选中的数据
const rowSelectionChange = (rowDataList: any) => {
   ids.value = rowDataList.map(rowData => rowData.id);
   emits('selectRows', ids.value)
}

// 双击数据行
const onRowDblClick = (record: any) => {
   emits('rowDblclick', record)
}

// 刷新表格数据
const refreshTableData = (reqParams: { page: number, limit: number}) => {
   const params = {
      page: reqParams.page,
      size: reqParams.limit,
   }
   currentPageSize.value = reqParams.limit
   emits('refresh', params)
}

// 回到第一页进行刷新
const refreshInitPage = () => {
   const params = {
      page: 1,
      size: currentPageSize.value,
   }
   // 重置页面
   currentPage.value = 1
   emits('refresh', params)
}

// 下载
const download = () => {
   if (props.download) {
      if (ids.value.length > 0) {
         props.download(ids.value)
      } else {
         props.download(props.data.map((rowData: any) => { return rowData.id }))
      }
   } else {
      console.log("默认下载")
   }
}
// 搜索
function toggleSearch() {
  emits("update:showSearch", !props.showSearch)
}

watch(
  () => props.columns,
  () => {
    if (props.columns) {
      // 显隐列初始默认隐藏列
      columnsList.value = props.columns.map((column: TableColumnItem) => {
        return {
          ...column,
          label: column.title,
          key: column.dataIndex,
          visible: true,
         //  disabled: true
        }
      })
    }
  }, {
    immediate: true
  }
)
</script>


<template>
   <div class="table-container">
       <div class="tool-bar">
          <slot name="toolBar">
             <ToolBar
                v-if="props.showToolBar"
                v-model:showSearch="props.showSearch"
                :btnTitle="props.btnTitle"
                :showSearchIcon="props.showSearchIcon"
                :columns="columnsList"
                :showColumnsType="props.showColumnsType"
                :hideLeftMenu="props.hideLeftMenu"
                @btn-click="$emit('btnClick')"
                @download="download"
                @refresh="refreshInitPage"
                @search="toggleSearch"
             >
                <template #leftMenu>
                   <slot name="leftMenu"></slot>
                </template>
             </ToolBar>
          </slot>  
       </div>
       <div class="table-wrapper">
          <el-table v-loading="props.tableLoading" :data="props.data" :max-height="props.maxHeight"  @selection-change="rowSelectionChange" @row-dblclick="onRowDblClick">
             <el-table-column v-if="props.showRowSelection" type="selection" width="55" align="center" :fixed="true" />
             <el-table-column
                v-for="columnItem in columnsList.filter(column => column.visible)"
                :key="columnItem.title"
                :label="columnItem.title"
                :min-width="columnItem.width"
                align="center"
                :prop="columnItem.dataIndex"
                :show-overflow-tooltip="columnItem.tooltip"
                :fixed="columnItem.fixed"
                :sortable="columnItem.sortable"
                :sort-orders="columnItem.sortOrders"
             >
                <template v-if="columnItem.slotName" #default="scope">
                   <!-- 在这里，scope.row 包含当前行的数据 -->
                   <slot :name="columnItem.slotName" :record="scope.row" :column="columnItem" :rowIndex="scope.$index">
                      <span>{{ scope.row[columnItem.dataIndex] }}</span>
                   </slot>
                </template>
             </el-table-column>
          </el-table>
       </div>
       <div class="pagination">
          <pagination
             v-show="props.showPagination && props.totalCount > 0"
             :total="props.totalCount"
             :layout="props.paginationLayout"
             v-model:page="currentPage"
             v-model:limit="currentPageSize"
             @pagination="refreshTableData"
             :pageSizes="props.pageSizes"
          />
       </div>
   </div>
 </template>

<style scoped>
.table-container {
   display: relative;
   flex-direction: column;
   height: 100%;
}
.tool-bar {
   flex: none;
   position: sticky;
   top: 0; /* 固定在顶部 */
   z-index: 11; /* 确保分页在表格上方 */
}
.table-wrapper {
  flex: 1; /* 填充剩余空间 */
  overflow: hidden;
  overflow-y: auto; /* 允许垂直滚动 */
}
.pagination {
  flex: none; /* 固定高度 */
  position: sticky;
  bottom: 0; /* 固定在底部 */
  background-color: white; /* 确保分页背景不透明 */
  align-items: center;
  z-index: 11; /* 确保分页在表格上方 */
}
:deep(.pagination-container) {
   margin-top: 0px;
   height: 60px;
}
/* 设置表格边框 */
:deep(.el-table__inner-wrapper) {
   border: 1px solid #E5E6EB;
}
/* 表头高度 */
:deep(.el-table .el-table__header-wrapper th, .el-table .el-table__fixed-header-wrapper th) {
   height: 50px !important;
}
/* 表格row */
:deep(.el-table .cell) {
   height: 50px;
   line-height: 50px;
   padding: 0px;
}
/* 去除padding对表格行高的影响 */
:deep(.el-table .el-table__cell) {
   padding: 0px;
}
:deep(.el-table--large .el-table__cell) {
   padding: 0px;
}
</style>